package com.hibase.core.excel.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hibase.common.exception.HibaseAssert;
import com.hibase.common.exception.HibaseException;
import com.hibase.core.excel.data.ReadAnalysisProcessor;
import com.hibase.core.excel.entity.MdsExcelBizDataDetail;
import com.hibase.core.excel.entity.MdsExcelImportConfig;
import com.hibase.core.excel.entity.MdsExcelImportConfigDetail;
import com.hibase.core.excel.exception.ExcelCommonException;
import com.hibase.core.excel.service.MdsExcelBizDataDetailService;
import com.hibase.core.excel.service.MdsExcelImportConfigDetailService;
import com.hibase.core.excel.service.MdsExcelImportConfigService;
import com.hibase.core.excel.vo.dynamic.DynamicExcelFieldInfo;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Excel配置工具类
 *
 * @author <a href="mailto:xiongliyi@hichain.com">Ian Xiong</a>
 * @since 1.4.35-V2
 */
@Slf4j
@Component
public class ExcelConfigUtil {
    @Autowired
    private MdsExcelBizDataDetailService mdsExcelBizDataDetailService;
    @Autowired
    private MdsExcelImportConfigService mdsExcelImportConfigService;
    @Autowired
    private MdsExcelImportConfigDetailService mdsExcelImportConfigDetailService;

    /**
     * 模板信息
     */
    @Getter
    private MdsExcelImportConfig excelTemplateInfo;

    /**
     * 数据读取监听器
     */
    @Getter
    private Class<? extends ReadAnalysisProcessor<?>> readAnalysisProcessor;

    @Getter
    private Map<String, Object> defaultValueMap;


    /**
     * 创建Excel导入模板
     *
     * @param mdsExcelImportConfigCode 业务数据模板ID
     * @return 返回模板类类型类型
     */
    @SneakyThrows
    public Class createTemplate(String mdsExcelImportConfigCode) {

        if (StrUtil.isBlank(mdsExcelImportConfigCode)) {
            throw new ExcelCommonException("Template Code cannot be null");
        }

        MdsExcelImportConfig mdsExcelImportConfig = null;
        if (StrUtil.isNotEmpty(mdsExcelImportConfigCode)) {
            mdsExcelImportConfig = mdsExcelImportConfigService.getByCode(mdsExcelImportConfigCode);
        } else {
            mdsExcelImportConfig = mdsExcelImportConfigService.getByDefaultConfig();
        }

        if (mdsExcelImportConfig == null) {
            log.debug("Excel导入配置模板信息不存在！");
            throw new ExcelCommonException("Mds_Excel_Import_Config cannot be null");
        }

        // custom read listener
        if (StrUtil.isNotEmpty(mdsExcelImportConfig.getReadListener())) {
            Class<?> clazz = Class.forName(mdsExcelImportConfig.getReadListener());
            readAnalysisProcessor = (Class<? extends ReadAnalysisProcessor<?>>) clazz;
        }

        if (StrUtil.isNotEmpty(mdsExcelImportConfig.getBeanName())) {
            HibaseAssert.notNull(mdsExcelImportConfig.getMethodName(), "beanMethod can't be empty");
        }

        excelTemplateInfo = mdsExcelImportConfig;

        return newInstance(mdsExcelImportConfig);
    }

    /**
     * 构建代理对象
     *
     * @param configInfo Excel配置信息
     * @return
     */
    private Class newInstance(MdsExcelImportConfig configInfo) {
        List<MdsExcelImportConfigDetail> configDetails = mdsExcelImportConfigDetailService.findByBizImportConfigId(configInfo.getId());
        HibaseAssert.notEmpty(configDetails, "Excel_Import_Config_Detail items cannot be null");
        Map<String, MdsExcelImportConfigDetail> excelConfigMap = configDetails.stream().collect(Collectors.toMap(item -> item.getBizDataDetailId(), item -> item));


        Map<String, MdsExcelBizDataDetail> excelTbMap = mdsExcelBizDataDetailService.findInIdsToMap(excelConfigMap.keySet());


        defaultValueMap = configDetails.stream().filter(item -> ObjectUtil.isAllNotEmpty(item.getDefaultValue())).collect(Collectors.toMap(
                item -> excelTbMap.get(item.getBizDataDetailId()).getFieldKey(), item -> item.getDefaultValue()));

        try {
            DynamicExcelFieldInfo dynamicExcelFieldInfo = getMdsExcelFieldInfo(configInfo, excelTbMap, excelConfigMap);

            return JavassistUtil.newInstance(dynamicExcelFieldInfo);
        } catch (Exception ex) {
            throw new HibaseException(ex.getMessage());
        }

    }

    /**
     * 构建 MdsExcelFieldInfo
     *
     * @param configInfo           配置信息
     * @param excelTbMap           Excel数据集详情Map
     * @param excelConfigDetailMap Excel导入模板配置Map
     * @return 返回 Excel 字段信息
     */
    private DynamicExcelFieldInfo getMdsExcelFieldInfo(
            MdsExcelImportConfig configInfo,
            Map<String, MdsExcelBizDataDetail> excelTbMap,
            Map<String, MdsExcelImportConfigDetail> excelConfigDetailMap) {

        DynamicExcelFieldInfo dynamicExcelFieldInfo = new DynamicExcelFieldInfo();
        // set templateId,version
        dynamicExcelFieldInfo.setTemplateId(configInfo.getId());
        dynamicExcelFieldInfo.setVersion(configInfo.getVersion());
        // set fields
        Map<String, DynamicExcelFieldInfo.FieldInfo> fieldInfoMap = Maps.newHashMap();

        excelConfigDetailMap.forEach((bizDataId, configDetail) -> {

            if (excelTbMap.containsKey(bizDataId)) {

                MdsExcelBizDataDetail bizDataDetail = excelTbMap.get(bizDataId);
                String fieldKey = bizDataDetail.getFieldKey();

                DynamicExcelFieldInfo.FieldInfo fieldInfo = new DynamicExcelFieldInfo.FieldInfo();
                fieldInfo.setIndex(configDetail.getColumnNum());

                List<String> headNames = Lists.newArrayList();
                if (StrUtil.isNotEmpty(configDetail.getColumnGroupName())) {
                    headNames.add(configDetail.getColumnGroupName());
                }
                if (StrUtil.isNotEmpty(configDetail.getColumnName())) {
                    headNames.add(configDetail.getColumnName());
                }
                if (CollUtil.isNotEmpty(headNames)) {
                    fieldInfo.setHeadNames(headNames.toArray(new String[]{}));
                }
                fieldInfo.setNotNull(bizDataDetail.getNotNull());

                fieldInfo.setDataType(bizDataDetail.getFieldType());

                if (StrUtil.isNotEmpty(configDetail.getConverter())) {
                    fieldInfo.setConverter(configDetail.getConverter());
                }

                fieldInfoMap.put(fieldKey, fieldInfo);
            }


        });


        dynamicExcelFieldInfo.setFields(fieldInfoMap);
        return dynamicExcelFieldInfo;
    }


}
